home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / tex / ascutils.zip / SPCTAB.ASM < prev    next >
Assembly Source File  |  1988-05-23  |  7KB  |  265 lines

  1. PAGE 55,130
  2. ;                 SPCTAB
  3. ;
  4.  
  5. bufspc        equ    0400h
  6. stkspc        equ    0100h
  7. midbuf        equ    0200h
  8.  
  9. codeseg        segment
  10.         assume    cs:codeseg, ds:codeseg
  11.  
  12.  
  13.         org    100h
  14.  
  15. spctab        proc    far
  16.  
  17. start:        jmp    init
  18.  
  19. ; messages -
  20. errmsg1        db    0Dh, 0Ah, 'Read Error',    0Dh, 0Ah, '$'
  21. errmsg2        db    0Dh, 0Ah, 'Could not get enough memory.', 0Dh, 0Ah, '$'
  22. help_msg    db    0Dh, 0Ah, 'SPCTAB is a filter that converts spaces'
  23.         db    ' in standard input to TABs in standard', 0Dh, 0Ah
  24.         db    'output where possible. It also trims a line, that'
  25.         db    ' is, it deletes all trailing',    0Dh, 0Ah
  26.         db    'spaces in a line.', 0Dh, 0Ah, 0Dh, 0Ah
  27.         db    'Usage: SPCTAB [<fname] [>fname]', 0Dh,    0Ah, '$'
  28. errmsg3        db    0Dh, 0Ah, 'Write Error', 0Dh, 0Ah, '$'
  29.  
  30. ; variables -
  31. count        dw    0
  32.  
  33. ; Note - space for the 1024 byte buffer    and the    256 byte stack is allocated
  34. ;     here, rather than being stored    in the task image on disk.
  35. ;
  36.  
  37. init:        mov    bx,offset buffer + bufspc + stkspc    ; req. mem.
  38.         add    bx,010h
  39.         mov    cl,4
  40.         shr    bx,cl            ; get it in paragraphs
  41.         mov    ah,04Ah            ; set it - cf=1    if error
  42.         int    021h
  43.         mov    dx,offset errmsg2
  44.         jc    err_exit        ; exit with error message
  45.         mov    ax,0
  46.         mov    di,offset buffer    ; else initialize buffer
  47.         mov    cx,bufspc + stkspc    ;  and stack space to 0
  48.         shr    cx,1            ;  (div    by 2 for words)
  49.         cld
  50.         rep    stosw
  51.         mov    sp,offset buffer + bufspc + stkspc    ; init sp
  52.  
  53.         mov    si,80h            ; get cmd line char count
  54.         cmp    byte ptr [si],0        ; into cx and incr by 1
  55.         je    Main
  56.         mov    cl,[si]
  57.         inc    cx
  58.  
  59. skpspc:        inc    si            ; skip any blanks
  60.         cmp    byte ptr [si],20h
  61.         loopz    skpspc
  62.  
  63.         jcxz    Main            ; skip if cmd line is all
  64.         cmp    byte ptr [si],3Fh    ; spaces.  Check for '?'
  65.         jne    Main            ; ignore other chars
  66.         mov    dx,offset help_msg    ; if '?' found,    exit with
  67.         jmp    short err_exit        ; 'help' message
  68.  
  69. Main:        call    get_line    ; get line from    std input
  70.         jc    err_exit    ; cf=1 is error
  71.         or    ax,ax
  72.         jz    norm_exit    ; 0 char count is end
  73.         call    fix_line    ; convert spcs to tabs
  74.         call    put_line    ; write    line to    std output
  75.         jc    err_exit    ; if cf=1, exit    with err msg
  76.         jmp    short Main    ; else continue.
  77.  
  78. ; Note - here err_exit outputs the messages to std error rather    than std
  79. ;    out, so    even if    I/O is redirected from the cmd line, the message
  80. ;    will be    output to the console rather than the output file.
  81.  
  82. err_exit:    mov    di,dx        ; point    di to error message
  83.         mov    cx,0FFh        ; set cx to 255    ( countdown limit )
  84.         mov    al,024h        ; "$"
  85.         cld
  86.         repnz    scasb        ; incr di to message terminator
  87.         dec    di        ; decr to last char of message
  88.         mov    cx,di        ; arithmetic to    get char count in cx
  89.         sub    cx,dx
  90.         mov    bx,2        ; handle for std error
  91.         mov    ah,040h        ; output message
  92.         int    021h
  93.         mov    al,1        ; exit status =    1
  94. norm_exit:    mov    ah,04Ch
  95.         int    021h
  96.  
  97. spctab        endp
  98.  
  99.  
  100. ;        SUBROUTINE
  101. ;        gets a line from std input
  102.  
  103. get_line    proc    near
  104.         mov    si,offset buffer
  105.  
  106. get_1:        mov    dx,si
  107.         mov    bx,0            ; handle for std input
  108.         mov    cx,1
  109.         mov    ah,03Fh            ; read cx chars
  110.         int    021h
  111.         jc    get_err            ; cf=1 if input    error
  112.         cmp    byte ptr [si],0Ah    ; eoln found
  113.         je    get_ok
  114.         or    ax,ax            ; ax=0 if kybd input eof
  115.         jz    get_ok
  116.         xor    ax,ax            ; (make ax=0 on eof)
  117.         cmp    byte ptr [si],1Ah    ; eof found (disk file)
  118.         je    get_ok
  119.         inc    si
  120.         jmp    short get_1
  121.  
  122. get_ok:        clc
  123.         ret
  124.  
  125. get_err:    mov    dx,offset errmsg1
  126.         stc
  127.         ret
  128.  
  129. get_line    endp
  130.  
  131.  
  132.  
  133. ;        SUBROUTINE
  134. ;        This is where the transformation takes place.
  135. ;        Basically, you're on your own to understand this.
  136. ;
  137.  
  138. fix_line    proc    near
  139.         mov    count,0
  140.         mov    si,offset buffer
  141.         mov    di,offset buffer + midbuf
  142.  
  143.         xor    bx,bx
  144.  
  145. fix_loop_1:    lodsb            ; get a    char (adv si)
  146.  
  147. bigloop:    cmp    al,020h        ; BL ?
  148.         je    fix_2        ;  yes,    next procedure.
  149.         cmp    al,0Dh        ; CR ?
  150.         jne    fix_1a
  151.         sub    di,bx        ; skip this if CR
  152.  
  153. fix_1a:        stosb            ; not BL, not CR, so store it (adv di)
  154.         cmp    al,9        ; HT ?
  155.         jne    fix_1b        ; if not, skip this
  156.         add    count,8        ; yes, add 8 to    count
  157.         and    count,0FFF8h    ; discard mod 8    remainder
  158.         inc    bx        ; incr bx value
  159.         jmp    short fix_loop_1    ; continue
  160.  
  161. fix_1b:        inc    count        ; non-space char, incr count
  162.         cmp    al,0Ah        ; check    for NL
  163.         je    fix_done    ; (exit    this scene - line done.)
  164.         xor    bx,bx        ; not NL, null bx value
  165.         jmp    short fix_loop_1    ; continue
  166. ; ----------
  167.  
  168. fix_2:        push    bx        ; point    bx to first BL input
  169.         mov    bx,si
  170.         dec    bx
  171.  
  172. fix_3:        lodsb            ; while    char is    BL, cont to get
  173.         cmp    al,020h
  174.         je    fix_3
  175.  
  176.         mov    dx,si        ; point    dx to last BL input
  177.         dec    dx
  178.         sub    dx,bx        ; subtract bx to get # of BL's
  179.         mov    ax,count    ; put count in ax and bx
  180.         mov    bx,ax
  181.         add    ax,8        ; advance ax to    next TS
  182.         and    ax,0FFF8h
  183.         sub    ax,bx        ; subtract pos of 1st BL in series
  184.         pop    bx        ; restore old bx value
  185.         xor    cx,cx        ; null cx
  186.         cmp    dx,ax
  187.         jb    fix_4        ; dx hasn't reached next TS yet
  188.         add    count,ax    ; dx reached next TS, add ax to    count
  189.         mov    bx,1        ; set bx value to 1
  190.         sub    dx,ax        ; move pointer back ax BL's
  191.         mov    al,9        ; output a Tab char.
  192.         stosb            ; (di is keeping track here)
  193.         mov    cx,dx        ; put dx value in cx
  194.         shr    cx,1        ; and divide by    8 (# of    TS's)
  195.         shr    cx,1
  196.         shr    cx,1
  197.  
  198. fix_4:        cmp    byte ptr [si-1],9    ; was last char    output a tab?
  199.         jne    fix_5        ; if not, skip this next
  200.         inc    cx        ; else add 1 TS
  201.         inc    si        ; incr char pointer
  202.         and    dx,0FFF8h    ; discard dx mod 8 remainder
  203.         jmp    short fix_4    ; continue while char =    tab.
  204.  
  205. fix_5:        or    cx,cx        ; if cx=0 skip this next
  206.         jz    fix_6
  207.         add    bx,cx        ; add cx to bx tab count
  208.         mov    ax,cx        ; put cx into ax
  209.         shl    ax,1        ; multiply by 8
  210.         shl    ax,1
  211.         shl    ax,1
  212.         add    count,ax    ; add ax to count
  213.         mov    al,9        ; put tab char in al
  214.         rep    stosb        ; output cx tabs (adv di)
  215.  
  216. fix_6:        mov    cx,dx        ; put output pointer in    cx
  217.         and    cx,7        ; cx mod 8
  218.         or    cx,cx        ; if it's 0, skip next
  219.         jz    fix_7
  220.         add    bx,cx        ; else add cx to bx counter
  221.         add    count,cx    ; add cx to count (?)
  222.         mov    al,020h        ; put BL in al
  223.         rep    stosb        ; output cx BL's (adv di)
  224.  
  225. fix_7:        mov    al,[si-1]    ; put that last    char back in al
  226.         jmp    bigloop        ; and do it again.
  227.  
  228. fix_done:    mov    cx,di        ; put di pointer in cx
  229.         sub    cx,offset buffer + midbuf    ; sub start of buffer
  230.         ret
  231.  
  232. fix_line    endp
  233.  
  234.  
  235.  
  236. ;        SUBROUTINE
  237. ;        sends line to std output
  238.  
  239. put_line    proc    near
  240.         jcxz    put_ok
  241.         push    cx            ; cx should have char count
  242.         mov    dx,offset buffer + midbuf
  243.         mov    bx,1            ; handle for std output
  244.         mov    ah,040h            ; output cx chars.
  245.         int    021h
  246.         pop    cx
  247.         jc    put_err            ; cf=1 if error.
  248.         sub    cx,ax            ; ax = cx if ok.
  249.         jnz    put_err
  250.  
  251. put_ok:        clc
  252.         ret
  253.  
  254. put_err:    mov    dx,offset errmsg3
  255.         stc
  256.         ret
  257.  
  258. put_line    endp
  259.  
  260.  
  261. buffer        db    0    ; buffer area:    1024 bytes allocated
  262.                 ; at pgm start (followed by 256    stack).
  263. codeseg        ends
  264.         end    start
  265.